#pragma once

#include <iostream>
#include <vector>
#include <unordered_map>
#include <string>
#include <fstream>
#include <assert.h>

#include "/usr/include/mysql/mysql.h"
#include "../Comm/Tool.hpp"
#include "../Comm/Log.hpp"

namespace Model_NS
{
    using namespace Tool_NS;
    using namespace Log_NS;

    const std::string oj_questions = "oj_questions";
    const std::string host = "127.0.0.1";
    const std::string user = "oj_server";
    const std::string password = "123456";
    const std::string db = "oj";
    const uint16_t port = 3306;

    class Question
    {
    public:
        std::string _number;     // 题号
        std::string _title;      // 标题
        std::string _difficulty; // 难度
        std::string _desc;       // 题目描述
        std::string _default;    // 为用户提供的预设代码
        std::string _test;       // 题目的测试代码
        int _cpu_limit;          // 时间限制 s
        int _mem_limit;          // 空间限制 KB
    };

    class Model
    {
    public:
        Model() {}
        ~Model() {}
    public:
        // 查询数据库
        bool QueryMySQL(const std::string& sql,std::vector<Question> *out)
        {
            // 1. 创建Mysql句柄 mysql_init
            MYSQL* my = mysql_init(nullptr);
            // 2. 设置连接的编码格式mysql_set_charset_set
            mysql_options(my,MYSQL_SET_CHARSET_NAME,"utf8");
            // 3. 连接数据库mysql_real_connect
            if(!mysql_real_connect(my,host.c_str(),user.c_str(),password.c_str(),db.c_str(),port,nullptr,0))
            {
                LOG(Fatal) << "连接数据库失败 : " << mysql_error(my) << std::endl;
                return false;
            }
            LOG(Info) << "连接数据库成功" << std::endl;
            // 4. 访问数据库/执行mysql语句 mysql_query
            mysql_query(my,sql.c_str());
            // 5. 提取结果 mysql_store_result
            MYSQL_RES* res = mysql_store_result(my);
            // 6. 分析结果 mysql_num_rows 获取行数 mysql_num_fields 获取列数 mysql_fetch_row获取行结果
            int rows = mysql_num_rows(res);
            int cols = mysql_num_fields(res);
            for(int i = 0 ; i < rows ; i++)
            {
                MYSQL_ROW row = mysql_fetch_row(res);
                Question q;

                q._number = row[0];
                q._title = row[1];
                q._difficulty = row[2];
                q._desc = row[3];
                q._default = row[4];
                q._test = row[5];
                q._cpu_limit = std::stoi(row[6]);
                q._mem_limit = std::stoi(row[7]);
                
                out->push_back(q);
            }
            // 7. 释放结果空间
            mysql_free_result(res);
            // 8. 关闭数据库链接 mysql_close
            mysql_close(my);

            return true;
        }

        // 获取所有题目
        bool GetAllQuestions(std::vector<Question> *out)
        {
            std::string sql = "select * from " + oj_questions;
            if(!QueryMySQL(sql,out))
            {
                return false;
            }

            return true;
        }

        // 获取特定题目
        bool GetOneQuestion(const std::string &number, Question *q)
        {
            bool ret = false;
            std::string sql = "select * from " + oj_questions + " where _number=" + number;
            std::cout << sql <<  std::endl;
            std::vector<Question> result;
            std::cout << " result.size()" << result.size() << std::endl;
            if(QueryMySQL(sql,&result))
            {
                if(result.size() == 1)
                {
                    *q = result[0];
                    ret = true;
                }
            }

            return ret;
        }

    private:
        std::unordered_map<std::string, Question> _questions;
    };
}